/* include/kernel/mm.h 
 * 
 * Copyright (C) 2021, 2022 intirain. 
 *
 * This file is part of evx. 
 * 
 * evx is free software: you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation, either version 3 of the License, or 
 * (at your option) any later version. 
 * 
 * evx is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with evx. If not, see <https://www.gnu.org/licenses/>
 */ 




#ifndef __MM_H
#define __MM_H


#ifndef __ASSEMBLER__


#include <sys/types.h>
#include <lib/klist.h>
#include <arch/archinfo.h>



/* a descriptor for each page to describe a page, hopely be smallest
 * and this is create only for the buddy memory management system. we 
 * can't implement that without this, because we need more memory when 
 * inserting. 
 *
 * we should initiallize this as late as we can, after maps okay. 
 * */

struct page {
	/* for cow, the reference count. we won't free if count-- 
	 * id of this page, can let freepage faster */
	__uint32_t 		info;

#define page_count(__p) 	((__p)->info & 0xffu)
#define page_id(__p) 		((__p)->info >> 24u)

	struct page 		*next;
};


/* okay, that's may only in the x86, but... */

struct zone {
	__uint32_t 		total_pages;

#define ZONETYPE_RAM 		1
#define ZONETYPE_OTHER 		0

	__uint32_t 		type;

	void 			*start_addr;
	
	struct page 		*pages;
};



/* the bucket_entry are for free objects. next_free points to next free
 * object. we replace the freeptr pointer in struct mempool and let that
 * points to old freeptr */

struct bucket_entry {
	struct bucket_entry 	*next;
};


#define CACHE_SIZE 		4096


struct mempool {
	int 			size, used;
	void 			*cache;
	struct bucket_entry 	*freeptr;

	/* it has the same size */
	struct mempool 		*next_pool;
};


struct mempool_dir {
	int 			size;
	struct mempool 		*pools;
};


void 			*__mempool_alloc(struct mempool *);
int 			__mempool_free(struct mempool *, void *);

void 			*kmalloc(int size);
int 			free_s(void *p, int size);

int 			kmalloc_report(void);
int 			dump_pool(struct mempool_dir *);

void 			*early_kmalloc(int nbytes, int align);
int 			early_free(void *p, int nbytes);

struct page 		*getfreepages(int nr, int mask);


#define free(p) 	early_free(p, 0)

/* nr_ram_pages is the total */
extern int nr_ram_pages, usable_ram_pages;


/* sets by arch_mm_init */

extern struct page 	*first_usable_ram, 
       			*kmem_pages;

#define kmem_zones 	((struct zone *) kernel_end)


/* they're really early but fast. actually, most free() did nothing
 * 
 * WARNING that you should't use align, because we didn't save old 
 * freeptr and it will be cracked by it: not freeable */


#endif

#endif

